package com.waigoulin.domain.order.service;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.waigoulin.domain.order.adapter.port.IProductPort;
import com.waigoulin.domain.order.adapter.repository.IOrderDaoRepository;
import com.waigoulin.domain.order.model.aggregate.CreateOrderAggregate;
import com.waigoulin.domain.order.model.entity.OrderEntity;
import com.waigoulin.domain.order.model.entity.PayOrderEntity;
import com.waigoulin.domain.order.model.entity.ProductEntity;
import com.waigoulin.domain.order.model.entity.ShopCartEntity;
import com.waigoulin.domain.order.model.valobj.OrderStatusVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * @FileName AbstractOrderService
 * @Description 抽象订单服务领域层接口实现类
 * @Author waigoulin
 * @date 2025-07-31
 **/
@Slf4j
public abstract class AbstractOrderService implements IOrderService {

    // 两个Bean类由private改为protected，以供子类使用
    protected final IOrderDaoRepository orderDaoRepository;

    protected final IProductPort productPort;

    // 用构造器注入
    public AbstractOrderService(IOrderDaoRepository orderDaoRepository, IProductPort productPort) {
        this.orderDaoRepository = orderDaoRepository;
        this.productPort = productPort;
    }

    @Override
    public PayOrderEntity createPayOrder(ShopCartEntity shopCartEntity) throws AlipayApiException {
        // 1. 查询当前用户是否存在未支付的订单或掉单订单
        // 掉单：用户提交订单后，系统未正常创建订单记录；或订单提交成功，但后续流程（如库存扣减、物流单生成）中断，导致订单 “消失” 或状态停滞。
        // 即只有流水单，没有支付单
        OrderEntity unpaidOrder = orderDaoRepository.queryUnPayOrder(shopCartEntity);
        if (unpaidOrder != null && OrderStatusVO.PAY_WAIT.equals(unpaidOrder.getOrderStatusVO())) {
            // 存在未支付订单，订单状态为PAY_WAIT，等待支付
            // 返回该未支付订单即可
            log.info("创建订单-存在，已存在未支付订单，userId:{} productId:{} orderId:{}", shopCartEntity.getUserId(), shopCartEntity.getProductId(), unpaidOrder.getOrderId());
            return PayOrderEntity.builder()
                    .orderId(unpaidOrder.getOrderId())
                    .payUrl(unpaidOrder.getPayUrl())
                    .build();
        } else if (unpaidOrder != null && OrderStatusVO.CREATE.equals(unpaidOrder.getOrderStatusVO())) {
            // 存在掉单订单，需要重新获得支付单
            // 订单状态转移路线：创建流水单(CREATE)->创建支付单(PAY_WAIT)->支付支付单(PAY_SUCCESS)->订单超时(CLOSE)
            // 需要将新创建的订单返回给用户支付，用户只需要知道订单的id和支付链接
            log.info("创建订单-存在，存在未创建支付单订单，创建支付单开始 userId:{} productId:{} orderId:{}", shopCartEntity.getUserId(), shopCartEntity.getProductId(), unpaidOrder.getOrderId());
            // 创建支付单
            PayOrderEntity payOrderEntity = doPrepareOrder(shopCartEntity.getUserId(), shopCartEntity.getProductId(), unpaidOrder.getProductName() ,unpaidOrder.getOrderId(), unpaidOrder.getTotalAmount());
            return PayOrderEntity.builder()
                    .orderId(payOrderEntity.getOrderId())
                    .payUrl(payOrderEntity.getPayUrl())
                    .build();
        }

        // 2. 查询商品并创建订单（本地的流水单和支付宝的支付单）
        // 2.1 查询商品
        ProductEntity productEntity = productPort.queryProductsByProductId(shopCartEntity.getProductId());
        // 2.2 创建流水单
        OrderEntity orderEntity = CreateOrderAggregate.buildOrderEntity(productEntity.getProductId(), productEntity.getProductName());
        CreateOrderAggregate createOrderAggregate = CreateOrderAggregate.builder()
                .userId(shopCartEntity.getUserId())
                .productEntity(productEntity)
                .orderEntity(orderEntity)
                .build();
        doSaveOrder(createOrderAggregate);
        // 2.3 创建支付单
        PayOrderEntity payOrderEntity = doPrepareOrder(shopCartEntity.getUserId(), productEntity.getProductId(), productEntity.getProductName(), orderEntity.getOrderId(), productEntity.getPrice());
        log.info("创建订单-完成，生成支付单，userId:{} orderId:{} payUrl:{}", payOrderEntity.getUserId(), payOrderEntity.getOrderId(), payOrderEntity.getPayUrl());
        // 需要将未支付的订单返回给用户支付，用户只需要知道订单的id和支付链接
        return PayOrderEntity.builder()
                .orderId(payOrderEntity.getOrderId())
                .payUrl(payOrderEntity.getPayUrl())
                .build();
    }

    protected abstract PayOrderEntity doPrepareOrder(String userId, String productId, String productName, String orderId, BigDecimal totalAmount) throws AlipayApiException;

    protected abstract void doSaveOrder(CreateOrderAggregate createOrderAggregate);
}


